library ieee;
use ieee.std_logic_1164.all;

entity ps2_kb_ctrl is
  port (
    reset     : in std_logic;
    clock     : in std_logic;

    dev_dat   : in std_logic;

    bit_rdy   : in std_logic;
    scode_rd  : in std_logic;

    timeout   : in std_logic;

    clr_rx    : out std_logic;
    rd_bit    : out std_logic;

    scode_rdy : out std_logic;

    start_wdt : out std_logic;
    stop_wdt  : out std_logic
  );
end entity ps2_kb_ctrl;

architecture default of ps2_kb_ctrl is
  type state_t is (START, DATA, STOP);

  signal state_reg : state_t;
  signal state_nxt : state_t;
begin
  process (reset, clock) is
  begin
    if reset = '1' then
      state_reg <= START;
    elsif rising_edge (clock) then
      state_reg <= state_nxt;
    end if;
  end process;

  process (state_reg, bit_rdy, scode_rd, dev_dat, timeout) is
  begin
    state_nxt <= state_reg;
    case state_reg is
      when START =>
        if bit_rdy = '1' then
          if dev_dat = '0' then
            state_nxt <= DATA;
          end if;
        end if;
      when DATA =>
        if scode_rd = '1' then
          state_nxt <= STOP;
        elsif timeout = '1' then
          state_nxt <= START;
        end if;
      when STOP =>
        if timeout = '1' then
          state_nxt <= START;
        elsif bit_rdy = '1' then
          state_nxt <= START;
        end if;
    end case;
  end process;

  process (state_reg, bit_rdy, dev_dat) is
  begin
    clr_rx <= '0';
    rd_bit <= '0';
    start_wdt <= '0';
    stop_wdt <= '0';
    scode_rdy <= '0';
    case state_reg is
      when START =>
        if bit_rdy = '1' then
          if dev_dat = '0' then
            clr_rx <= '1';
            start_wdt <= '1';
          end if;
        end if;
      when DATA =>
        if bit_rdy = '1' then
          rd_bit <= '1';
        end if;
      when STOP =>
        if bit_rdy = '1' then
          stop_wdt <= '1';
          if dev_dat = '1' then
            scode_rdy <= '1';
          end if;
        end if;
    end case;
  end process;
end architecture default;
